package com.vast.vastlcd.lcdAPI;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.PaletteData;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.PlatformUI;

import com.vast.vastlcd.views.ImageView;

/**
 * 
 */
public class LCDSetImageRequest {

	/**
	 * 
	 */
	public LCDMessageHeader lcdMessageHeader = new LCDMessageHeader();
	
	/**
	 * 
	 */
	public int nImageSize;
	
	/**
	 * 
	 */
	public int nSequence;
	
	/**
	 * 
	 */
	public int nBufferSize;
	
	/**
	 * 
	 */
	public int nLastBuffer;
	
	/**
	 * 
	 */
	public int nHasHeader;
	
	/**
	 * 
	 */
	public int nBitsPerPixel;
	
	/**
	 * 
	 */
	public int nX;
	
	/**
	 * 
	 */
	public int nY;
	
	/**
	 * 
	 */
	public int nCX;
	
	/**
	 * 
	 */
	public int nCY;
	
	/**
	 * 
	 */
	public int nOption;
	
	/**
	 * 
	 */
	public byte[] bufferData;
	
	/**
	 * 
	 */
	static byte[] fullImageData; 
	
	/**
	 * 
	 */
	static int currOffset; 
	
	/**
	 * 
	 */
	static int pingPongCount = 0;
	
	/**
	 * 
	 */
	static Image pingPongImage0;
	
	/**
	 * 
	 */
	static Image pingPongImage1;
	
	// Pallete appears to be BGR, not RGB
	private PaletteData palette = new PaletteData(0x0000FF, 0x00FF00, 0xFF0000);
	
	/**
	 * @return
	 */
	public byte[] javaToNative () {
		if (this == null) 
	 		return null;
	 	
	 	byte[] buffer = null;
	 	try {
			// write data to a byte array and then ask super to convert to pMedium
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			LCDDataOutputStream writeOut = new LCDDataOutputStream(out);
			
			writeOut.write(lcdMessageHeader.javaToNative());
			
			writeOut.writeLSBInt(nImageSize);
			writeOut.writeLSBInt(nSequence);
			writeOut.writeLSBInt(nBufferSize);
			writeOut.writeLSBInt(nLastBuffer);
			writeOut.writeLSBInt(nHasHeader);
			writeOut.writeLSBInt(nBitsPerPixel);
			writeOut.writeLSBInt(nX);
			writeOut.writeLSBInt(nY);
			writeOut.writeLSBInt(nCX);
			writeOut.writeLSBInt(nCY);
			writeOut.writeLSBInt(nOption);
 			writeOut.write(bufferData);
			
			buffer = out.toByteArray();
			writeOut.close();			
			
		} catch (IOException e) {

		}
		return buffer;
	}
	
	/**
	 * @param buffer
	 * @return
	 */
	static public LCDSetImageRequest nativeToJava(byte[] buffer){		 
 		if (buffer == null) 
 			return null;
 		
 		LCDSetImageRequest sir = new LCDSetImageRequest();
 		try {
 			ByteArrayInputStream in = new ByteArrayInputStream(buffer);
 			LCDDataInputStream readIn = new LCDDataInputStream(in); 			
 			 
 			sir.nImageSize = readIn.readLSBInt();
 			sir.nSequence = readIn.readLSBInt();
 			sir.nBufferSize = readIn.readLSBInt();
 			sir.nLastBuffer = readIn.readLSBInt();
 			sir.nHasHeader = readIn.readLSBInt();
 			sir.nBitsPerPixel = readIn.readLSBInt();
 			sir.nX = readIn.readLSBInt();
 			sir.nY = readIn.readLSBInt();
 			sir.nCX = readIn.readLSBInt();
 			sir.nCY = readIn.readLSBInt();
 			sir.nOption = readIn.readLSBInt();
 			
 			sir.bufferData = new byte[sir.nBufferSize];
 			readIn.read(sir.bufferData);
 			
 			/*System.out.println("header " + sir.nHasHeader);
			System.out.println("option " + sir.nOption);
			System.out.println("nImageSize " + sir.nImageSize);
			System.out.println("nBufferSize " + sir.nBufferSize);
			System.out.println("bpp " + sir.nBitsPerPixel);	*/		
 			
 			readIn.close();
 		} catch (IOException ex) {
 			return null;
 		}
 		
 		return sir; 		
	}
	 
	/**
	 * @param msgBodyBuffer
	 */
	static void processMessage(byte[] msgBodyBuffer) {
		LCDSetImageRequest sir = nativeToJava(msgBodyBuffer);		 
		sir.updateViewer();		
	}
	
	/**
	 * 
	 */
	void updateViewer() {
		// set the position of the window
		if (PlatformUI.isWorkbenchRunning()) {
				
			if(nSequence == 0) {				
				// Can we delete the old buffer??
				if ((fullImageData == null) || (fullImageData.length != nImageSize))
					fullImageData = new byte[nImageSize];
				
				currOffset = 0;
			}
			
			if ((currOffset + nBufferSize) > nImageSize) {
				System.out.println("Error: Buffer overflow.");
				return;
			}
				
			System.arraycopy(bufferData, 0, fullImageData, currOffset, nBufferSize);
			
			currOffset = currOffset + nBufferSize;
			
			// If it's the last buffer update the display
			if(nLastBuffer == 1)
			{
				IWorkbench wb = PlatformUI.getWorkbench();	
				final Display display = wb.getDisplay();
				
				// Async runnables to keep CoMET alive
				display.asyncExec (new Runnable () {
					public void run () {
						while (display.isDisposed())
						{}
						
						// If there is a header then Java should be able to load 
						// the image itself
						if (nHasHeader == 1) {
							ByteArrayInputStream ImageStream 
								= new ByteArrayInputStream(fullImageData);
							if (pingPongCount == 0) 
								pingPongImage0 = new Image(display, ImageStream);						
							else 
								pingPongImage1 = new Image(display, ImageStream);
								
							
						}
						// ... otherwise we need to set up some basic info about 
						// the image
						else {							
							ImageData id = new ImageData(
									 nCX,
					                 nCY,
					                 nBitsPerPixel,
					                 palette,
					                 nCX * (nBitsPerPixel / 8),
					                 fullImageData);
							if (pingPongCount == 0) 
								pingPongImage0 = new Image(display, id);						
							else 
								pingPongImage1 = new Image(display, id);
						}
					
						if (pingPongCount == 0) {
							ImageView.setImage(pingPongImage0);
							if (pingPongImage1 != null)
								pingPongImage1.dispose();
							pingPongCount = 1;
						}
						else {
							ImageView.setImage(pingPongImage1);
							if (pingPongImage0 != null)
								pingPongImage0.dispose();
							pingPongCount = 0;
						}
					}
				});	
			}											
		}
	}
}
